Partager via


Tests unitaires dans les compléments Office

Les tests unitaires case activée les fonctionnalités de votre complément sans nécessiter de connexions réseau ou de service, y compris les connexions à l’application Office. Les tests unitaires du code côté serveur et du code côté client qui n’appelle pasles API JavaScript Office sont les mêmes dans les compléments Office que dans n’importe quelle application web. Il ne nécessite donc aucune documentation spéciale. Toutefois, le code côté client qui appelle les API JavaScript Office est difficile à tester. Pour résoudre ces problèmes, nous avons créé une bibliothèque pour simplifier la création d’objets Office fictifs dans les tests unitaires : Office-Addin-Mock. La bibliothèque facilite les tests des manières suivantes :

  • Les API JavaScript Office doivent s’initialiser dans un contrôle webview dans le contexte d’une application Office (Excel, Word, etc.), de sorte qu’elles ne peuvent pas être chargées dans le processus dans lequel les tests unitaires s’exécutent sur votre ordinateur de développement. La bibliothèque Office-Addin-Mock peut être importée dans vos fichiers de test, ce qui permet la simulation des API JavaScript Office à l’intérieur du processus Node.js dans lequel les tests s’exécutent.
  • Les API spécifiques à l’application ont des méthodes de charge et de synchronisation qui doivent être appelées dans un ordre particulier par rapport aux autres fonctions et entre elles. En outre, la load méthode doit être appelée avec certains paramètres en fonction des propriétés des objets Office qui seront lues par le code ultérieurement dans la fonction testée. Toutefois, les frameworks de test unitaire étant par nature sans état, ils ne peuvent pas conserver un enregistrement indiquant si load ou sync a été appelé ou quels paramètres ont été passés à load. Les objets fictifs que vous créez avec la bibliothèque Office-Addin-Mock ont un état interne qui effectue le suivi de ces éléments. Cela permet aux objets fictifs d’émuler le comportement d’erreur des objets Office réels. Par exemple, si la fonction en cours de test tente de lire une propriété qui n’a pas été transmise à la première fois à load, le test retourne une erreur similaire à celle renvoyée par Office.

La bibliothèque ne dépend pas des API JavaScript Office et peut être utilisée avec n’importe quelle infrastructure de test unitaire JavaScript, par exemple :

Les exemples de cet article utilisent l’infrastructure Jest. Vous trouverez des exemples d’utilisation de l’infrastructure Mocha dans la page d’accueil Office-Addin-Mock.

Configuration requise

Cet article part du principe que vous connaissez les concepts de base des tests unitaires et de la simulation, notamment comment créer et exécuter des fichiers de test, et que vous avez une certaine expérience avec une infrastructure de tests unitaires.

Conseil

Si vous utilisez Visual Studio, nous vous recommandons de lire l’article Tests unitaires JavaScript et TypeScript dans Visual Studio pour obtenir des informations de base sur les tests unitaires JavaScript dans Visual Studio, puis de revenir à cet article.

Installer l’outil

Pour installer la bibliothèque, ouvrez une invite de commandes, accédez à la racine de votre projet de complément, puis entrez la commande suivante.

npm install office-addin-mock --save-dev

Utilisation de base

  1. Votre projet aura un ou plusieurs fichiers de test. (Consultez les instructions relatives à votre infrastructure de test et les exemples de fichiers de test dans Exemples ci-dessous.) Importez la bibliothèque, avec ou requireimport mot clé, dans n’importe quel fichier de test qui a un test d’une fonction qui appelle les API JavaScript Office, comme illustré dans l’exemple suivant.

    const OfficeAddinMock = require("office-addin-mock");
    
  2. Importez le module qui contient la fonction de complément que vous souhaitez tester avec ou requireimport mot clé. Voici un exemple qui suppose que votre fichier de test se trouve dans un sous-dossier du dossier contenant les fichiers de code de votre complément.

    const myOfficeAddinFeature = require("../my-office-add-in");
    
  3. Créez un objet de données qui a les propriétés et sous-propriétés que vous devez simuler pour tester la fonction. Voici un exemple d’objet qui simule la propriété Workbook.range.address Excel et la méthode Workbook.getSelectedRange . Il ne s’agit pas du dernier objet fictif. Considérez-le comme un objet de départ utilisé par OfficeMockObject pour créer l’objet fictive final.

    const mockData = {
      workbook: {
        range: {
          address: "C2:G3",
        },
        getSelectedRange: function () {
          return this.range;
        },
      },
    };
    
  4. Passez l’objet de données au OfficeMockObject constructeur. Notez ce qui suit à propos de l’objet retourné OfficeMockObject .

    • Il s’agit d’une simulation simplifiée d’un objet OfficeExtension.ClientRequestContext .
    • L’objet fictive a tous les membres de l’objet de données et a également des implémentations fictives des load méthodes et sync .
    • L’objet fictif imite le comportement d’erreur crucial de l’objet ClientRequestContext . Par exemple, si l’API Office que vous testez tente de lire une propriété sans d’abord charger la propriété et appeler sync, le test échoue avec une erreur similaire à ce qui serait levée dans le runtime de production : « Erreur, propriété non chargée ».
    const contextMock = new OfficeAddinMock.OfficeMockObject(mockData);
    

    Remarque

    La documentation de référence complète pour le OfficeMockObject type se trouve dans Office-Addin-Mock.

  5. Dans la syntaxe de votre infrastructure de test, ajoutez un test de la fonction . Utilisez l’objet OfficeMockObject à la place de l’objet qu’il simule, dans ce cas l’objet ClientRequestContext . L’exemple suivant continue dans Jest. Cet exemple de test suppose que la fonction de complément testée est appelée getSelectedRangeAddress, qu’elle prend un ClientRequestContext objet comme paramètre et qu’elle est destinée à retourner l’adresse de la plage actuellement sélectionnée. L’exemple complet est plus loin dans cet article.

    test("getSelectedRangeAddress should return the address of the range", async function () {
      expect(await getSelectedRangeAddress(contextMock)).toBe("C2:G3");
    });
    
  6. Exécutez le test conformément à la documentation de l’infrastructure de test et de vos outils de développement. En règle générale, il existe un fichier package.json avec un script qui exécute l’infrastructure de test. Par exemple, si Jest est le framework, package.json contient les éléments suivants :

    "scripts": {
      "test": "jest",
      -- other scripts omitted --  
    }
    

    Pour exécuter le test, entrez ce qui suit dans une invite de commandes à la racine du projet.

    npm test
    

Exemples

Les exemples de cette section utilisent Jest avec ses paramètres par défaut. Ces paramètres prennent en charge les modules CommonJS. Consultez la documentation Jest pour savoir comment configurer Jest et Node.js pour prendre en charge les modules ECMAScript et pour prendre en charge TypeScript. Pour exécuter l’un de ces exemples, procédez comme suit.

  1. Créez un projet de complément Office pour l’application hôte Office appropriée (par exemple, Excel ou Word). L’une des façons de procéder rapidement consiste à utiliser le générateur Yeoman pour les compléments Office.
  2. À la racine du projet, installez Jest.
  3. Installez l’outil office-addin-mock.
  4. Créez un fichier exactement comme le premier fichier de l’exemple et ajoutez-le au dossier qui contient les autres fichiers sources du projet, souvent appelés \src.
  5. Créez un sous-dossier dans le dossier du fichier source et attribuez-lui un nom approprié, par exemple \tests.
  6. Créez un fichier exactement comme le fichier de test dans l’exemple et ajoutez-le au sous-dossier.
  7. Ajoutez un test script au fichier package.json , puis exécutez le test, comme décrit dans Utilisation de base.

Simulation des API courantes d’Office

Cet exemple suppose un complément Office pour tout hôte qui prend en charge les API communes Office (par exemple, Excel, PowerPoint ou Word). Le complément a l’une de ses fonctionnalités dans un fichier nommé my-common-api-add-in-feature.js. L’exemple suivant montre le contenu du fichier. La addHelloWorldText fonction définit le texte « Hello World! » sur tout ce qui est actuellement sélectionné dans le document, par exemple, une plage dans Word, une cellule dans Excel ou une zone de texte dans PowerPoint.

const myCommonAPIAddinFeature = {

    addHelloWorldText: async () => {
        const options = { coercionType: Office.CoercionType.Text };
        await Office.context.document.setSelectedDataAsync("Hello World!", options);
    }
}
  
module.exports = myCommonAPIAddinFeature;

Le fichier de test, nommé my-common-api-add-in-feature.test.js se trouve dans un sous-dossier, par rapport à l’emplacement du fichier de code du complément. L’exemple suivant montre le contenu du fichier. Notez que la propriété de niveau supérieur est context, un objet Office.Context , de sorte que l’objet qui est simulé est le parent de cette propriété : un objet Office . Tenez compte des informations suivantes à propos de ce code :

  • Le OfficeMockObject constructeur n’ajoute pas toutes les classes d’énumération Office à l’objet fictive Office . Par conséquent, la CoercionType.Text valeur référencée dans la méthode de complément doit être ajoutée explicitement dans l’objet seed.
  • Étant donné que la bibliothèque JavaScript Office n’est pas chargée dans le processus de nœud, l’objet Office référencé dans le code du complément doit être déclaré et initialisé.
const OfficeAddinMock = require("office-addin-mock");
const myCommonAPIAddinFeature = require("../my-common-api-add-in-feature");

// Create the seed mock object.
const mockData = {
    context: {
      document: {
        setSelectedDataAsync: function (data, options) {
          this.data = data;
          this.options = options;
        },
      },
    },
    // Mock the Office.CoercionType enum.
    CoercionType: {
      Text: {},
    },
};
  
// Create the final mock object from the seed object.
const officeMock = new OfficeAddinMock.OfficeMockObject(mockData);

// Create the Office object that is called in the addHelloWorldText function.
global.Office = officeMock;

/* Code that calls the test framework goes below this line. */

// Jest test
test("Text of selection in document should be set to 'Hello World'", async function () {
    await myCommonAPIAddinFeature.addHelloWorldText();
    expect(officeMock.context.document.data).toBe("Hello World!");
});

Simulation des API Outlook

Bien qu’à proprement parler, les API Outlook fassent partie du modèle d’API commune, elles ont une architecture spéciale qui est construite autour de l’objet Mailbox . Nous avons donc fourni un exemple distinct pour Outlook. Cet exemple suppose qu’un Outlook possède l’une de ses fonctionnalités dans un fichier nommé my-outlook-add-in-feature.js. L’exemple suivant montre le contenu du fichier. La addHelloWorldText fonction définit le texte « Hello World! » sur ce qui est actuellement sélectionné dans la fenêtre de composition du message.

const myOutlookAddinFeature = {

    addHelloWorldText: async () => {
        Office.context.mailbox.item.setSelectedDataAsync("Hello World!");
      }
}

module.exports = myOutlookAddinFeature;

Le fichier de test, nommé my-outlook-add-in-feature.test.js se trouve dans un sous-dossier, par rapport à l’emplacement du fichier de code du complément. L’exemple suivant montre le contenu du fichier. Notez que la propriété de niveau supérieur est context, un objet Office.Context , de sorte que l’objet qui est simulé est le parent de cette propriété : un objet Office . Tenez compte des informations suivantes à propos de ce code :

  • La host propriété sur l’objet fictive est utilisée en interne par la bibliothèque fictive pour identifier l’application Office. Il est obligatoire pour Outlook. Il ne sert actuellement à aucune autre application Office.
  • Étant donné que la bibliothèque JavaScript Office n’est pas chargée dans le processus de nœud, l’objet Office référencé dans le code du complément doit être déclaré et initialisé.
const OfficeAddinMock = require("office-addin-mock");
const myOutlookAddinFeature = require("../my-outlook-add-in-feature");

// Create the seed mock object.
const mockData = {
  // Identify the host to the mock library (required for Outlook).
  host: "outlook",
  context: {
    mailbox: {
      item: {
          setSelectedDataAsync: function (data) {
          this.data = data;
        },
      },
    },
  },
};
  
// Create the final mock object from the seed object.
const officeMock = new OfficeAddinMock.OfficeMockObject(mockData);

// Create the Office object that is called in the addHelloWorldText function.
global.Office = officeMock;

/* Code that calls the test framework goes below this line. */

// Jest test
test("Text of selection in message should be set to 'Hello World'", async function () {
    await myOutlookAddinFeature.addHelloWorldText();
    expect(officeMock.context.mailbox.item.data).toBe("Hello World!");
});

Simulation des API spécifiques à l’application Office

Lorsque vous testez des fonctions qui utilisent les API spécifiques à l’application, veillez à simuler le type d’objet approprié. Il existe deux options :

  • Simuler un Objet OfficeExtension.ClientRequestObject. Procédez ainsi lorsque la fonction testée remplit les deux conditions suivantes :

    • Il n’appelle pas un hôte.run fonction, telle qu’Excel.run.
    • Il ne fait référence à aucune autre propriété ou méthode directe d’un objet Host .
  • Simuler un objet Host, tel qu’Excel ou Word. Effectuez cette opération lorsque l’option précédente n’est pas possible.

Les sous-sections ci-dessous présentent des exemples de ces deux types de tests.

Remarque

La bibliothèque Office-Addin-Mock ne prend actuellement pas en charge les objets de type de collection fictifs, qui sont tous les objets dans les API spécifiques à l’application qui sont nommés sur le modèle *Collection, comme WorksheetCollection. Nous travaillons d’arrache-pied pour ajouter cette prise en charge à la bibliothèque.

Simulation d’un objet ClientRequestContext

Cet exemple suppose qu’un complément Excel possède l’une de ses fonctionnalités dans un fichier nommé my-excel-add-in-feature.js. L’exemple suivant montre le contenu du fichier. Notez que est getSelectedRangeAddress une méthode d’assistance appelée à l’intérieur du rappel qui est passé à Excel.run.

const myExcelAddinFeature = {
    
    getSelectedRangeAddress: async (context) => {
        const range = context.workbook.getSelectedRange();      
        range.load("address");

        await context.sync();
      
        return range.address;
    }
}

module.exports = myExcelAddinFeature;

Le fichier de test, nommé my-excel-add-in-feature.test.js se trouve dans un sous-dossier, par rapport à l’emplacement du fichier de code du complément. L’exemple suivant montre le contenu du fichier. Notez que la propriété de niveau supérieur est workbook, de sorte que l’objet qui est simulé est le parent d’un Excel.Workbookobjet : un ClientRequestContext objet .

const OfficeAddinMock = require("office-addin-mock");
const myExcelAddinFeature = require("../my-excel-add-in-feature");

// Create the seed mock object.
const mockData = {
    workbook: {
      range: {
        address: "C2:G3",
      },
      // Mock the Workbook.getSelectedRange method.
      getSelectedRange: function () {
        return this.range;
      },
    },
};

// Create the final mock object from the seed object.
const contextMock = new OfficeAddinMock.OfficeMockObject(mockData);

/* Code that calls the test framework goes below this line. */

// Jest test
test("getSelectedRangeAddress should return address of selected range", async function () {
  expect(await myOfficeAddinFeature.getSelectedRangeAddress(contextMock)).toBe("C2:G3");
});

Simulation d’un objet hôte

Cet exemple suppose qu’un complément Word a l’une de ses fonctionnalités dans un fichier nommé my-word-add-in-feature.js. L’exemple suivant montre le contenu du fichier.

const myWordAddinFeature = {

  insertBlueParagraph: async () => {
    return Word.run(async (context) => {
      // Insert a paragraph at the end of the document.
      const paragraph = context.document.body.insertParagraph("Hello World", Word.InsertLocation.end);
  
      // Change the font color to blue.
      paragraph.font.color = "blue";
  
      await context.sync();
    });
  }
}

module.exports = myWordAddinFeature;

Le fichier de test, nommé my-word-add-in-feature.test.js se trouve dans un sous-dossier, par rapport à l’emplacement du fichier de code du complément. L’exemple suivant montre le contenu du fichier. Notez que la propriété de niveau supérieur est context, un ClientRequestContext objet , de sorte que l’objet qui est simulé est le parent de cette propriété : un Word objet . Tenez compte des informations suivantes à propos de ce code :

  • Lorsque le OfficeMockObject constructeur crée l’objet fictif final, il s’assure que l’objet enfant ClientRequestContext a sync des méthodes et load .
  • Le OfficeMockObject constructeur n’ajoute pas de run fonction à l’objet fictif Word . Elle doit donc être ajoutée explicitement dans l’objet seed.
  • Le OfficeMockObject constructeur n’ajoute pas toutes les classes d’énumération Word à l’objet fictifWord. Par conséquent, la InsertLocation.end valeur référencée dans la méthode de complément doit être ajoutée explicitement dans l’objet initial.
  • Étant donné que la bibliothèque JavaScript Office n’est pas chargée dans le processus de nœud, l’objet Word référencé dans le code du complément doit être déclaré et initialisé.
const OfficeAddinMock = require("office-addin-mock");
const myWordAddinFeature = require("../my-word-add-in-feature");

// Create the seed mock object.
const mockData = {
  context: {
    document: {
      body: {
        paragraph: {
          font: {},
        },
        // Mock the Body.insertParagraph method.
        insertParagraph: function (paragraphText, insertLocation) {
          this.paragraph.text = paragraphText;
          this.paragraph.insertLocation = insertLocation;
          return this.paragraph;
        },
      },
    },
  },
  // Mock the Word.InsertLocation enum.
  InsertLocation: {
    end: "end",
  },
  // Mock the Word.run function.
  run: async function(callback) {
    await callback(this.context);
  },
};

// Create the final mock object from the seed object.
const wordMock = new OfficeAddinMock.OfficeMockObject(mockData);

// Define and initialize the Word object that is called in the insertBlueParagraph function.
global.Word = wordMock;

/* Code that calls the test framework goes below this line. */

// Jest test set
describe("Insert blue paragraph at end tests", () => {

  test("color of paragraph", async function () {
    await myWordAddinFeature.insertBlueParagraph();  
    expect(wordMock.context.document.body.paragraph.font.color).toBe("blue");
  });

  test("text of paragraph", async function () {
    await myWordAddinFeature.insertBlueParagraph();
    expect(wordMock.context.document.body.paragraph.text).toBe("Hello World");
  });
})

Remarque

La documentation de référence complète pour le OfficeMockObject type se trouve dans Office-Addin-Mock.

Voir aussi